package mobi.smarthosts;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Vector;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

public final class ViewHelper {

    public static final LinearLayout.LayoutParams COMMON_LINEAR_LAYOUT_PARAMS =
        new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
                                      LinearLayout.LayoutParams.WRAP_CONTENT);
    static {
        COMMON_LINEAR_LAYOUT_PARAMS.leftMargin = 3;
        COMMON_LINEAR_LAYOUT_PARAMS.rightMargin = 3;
    }

    public static final LinearLayout.LayoutParams COMMON_LINEAR_LAYOUT_PARAMS_2 =
            new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
                                          LinearLayout.LayoutParams.WRAP_CONTENT);
        static {
            COMMON_LINEAR_LAYOUT_PARAMS_2.topMargin = 7;
            COMMON_LINEAR_LAYOUT_PARAMS_2.rightMargin = 7;
            COMMON_LINEAR_LAYOUT_PARAMS_2.bottomMargin = 7;
            COMMON_LINEAR_LAYOUT_PARAMS_2.leftMargin = 7;
        }

    public static final ViewGroup.LayoutParams LAYOUT_PARAMS_COMMON =
        new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                                      ViewGroup.LayoutParams.WRAP_CONTENT);

    public static final ViewGroup.LayoutParams LAYOUT_PARAMS_FILL_PARENT =
        new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                                      ViewGroup.LayoutParams.FILL_PARENT);

    public static final RadioGroup.OnCheckedChangeListener TOGGLE_LISTENER =
        new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(final RadioGroup radioGroup, final int i) {
            for (int j = 0; j < radioGroup.getChildCount(); j++) {
                final CompoundButton view = (CompoundButton) radioGroup.getChildAt(j);
                view.setChecked(view.getId() == i);
            }
        }
    };

    /**
     * Hide Constructor.
     */
    private ViewHelper() {}

    /**
     *
     * @param dialog
     * @return
     */
    public static WindowManager.LayoutParams fixDialogLayout(Dialog dialog) {
        WindowManager.LayoutParams layout = new WindowManager.LayoutParams();
        layout.copyFrom(dialog.getWindow().getAttributes());
        layout.width = WindowManager.LayoutParams.FILL_PARENT;
        layout.height = WindowManager.LayoutParams.FILL_PARENT;
        return layout;
    }

    public static void removeViewFromParent(View view) {
        if (view == null) return;
        ViewGroup parentView = (ViewGroup) view.getParent();
        if (parentView == null) return;
        parentView.removeView(view);
    }

    /**
     * Convenient method to retrieve value from TextView.
     *
     * @param viewId the assigned view must be inherited from TextView
     * @param RootView accept any Object has <code>findViewById()</code> method.
     * @return
     */
    public static String getViewText(int viewId, Object rootView) {
        try {
            TextView view = resolveTextView(viewId, rootView);
            return view.getText().toString();
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * Convenient method to retrieve value from TextView.
     *
     * @param viewId the assigned view must be inherited from TextView
     * @param rootView accept any Object has <code>findViewById()</code> method.
     * @param color actual color that will be set. For color from Resource, use
     *              Context.getResources().getColor() to get the real color
     */
    public static void setViewTextColor(int viewId, Object rootView, int color) {
        TextView view = resolveTextView(viewId, rootView);
        if (view != null) view.setTextColor(color);
    }

    /**
     * Convenient method to set Text value for TextView.
     *
     * @param viewId the assigned view must be inherited from TextView
     * @param rootView accept any Object has <code>findViewById()</code> method.
     */
    public static void setViewText(int viewId, Object rootView, String text) {
        TextView view = resolveTextView(viewId, rootView);
        if (view != null) view.setText(text);
    }

    /**
     * Convenient method to set Text value for TextView.
     *
     * @param viewId the assigned view must be inherited from TextView
     * @param rootView accept any Object has <code>findViewById()</code> method.
     */
    public static void setViewText(int viewId, Object rootView, int textResId) {
        TextView view = resolveTextView(viewId, rootView);
        if (view != null) view.setText(textResId);
    }

    public static void setImageSource(int viewId, Object rootView, int resId) {
        ImageView view = resolveImageView(viewId, rootView);
        if (view != null) view.setImageResource(resId);
    }

    public static void setImageSource(int viewId, Object rootView, Bitmap bitmap) {
        ImageView view = resolveImageView(viewId, rootView);
        if (view != null) view.setImageBitmap(bitmap);
    }

    public static void setImageSource(int viewId, Object rootView, Drawable drawable) {
        ImageView view = resolveImageView(viewId, rootView);
        if (view != null) view.setImageDrawable(drawable);
    }

    public static void setImageSource(int viewId, Object rootView, File file) {
        ImageView view = resolveImageView(viewId, rootView);
        if (view != null) view.setImageURI(Uri.fromFile(file));
    }

    private static TextView resolveTextView(int viewId, Object rootView) {
        Method method;
        TextView view = null;
        try {
            method = rootView.getClass().getMethod("findViewById", int.class);
            view = (TextView) method.invoke(rootView, viewId);
        } catch (Exception e) {
            Log.w("Cannot find view "+viewId);
        }

        return view;
    }

    private static ImageView resolveImageView(int viewId, Object rootView) {
        Method method;
        ImageView view = null;
        try {
            method = rootView.getClass().getMethod("findViewById", int.class);
            view = (ImageView) method.invoke(rootView, viewId);
        } catch (Exception e) {
            Log.w("Cannot find view "+viewId);
        }

        return view;
    }

    public static void showToast(final Context context, final String message) {
        showToast(context, message, Toast.LENGTH_SHORT);
    }

    public static void showToast(final Context context, final String message,
            final int duration) {
        if (context == null) return;
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(context, message, duration).show();
            }
        });
    }

    public static void showToast(final Context context, final int messageResId) {
        showToast(context, messageResId, Toast.LENGTH_SHORT);
    }

    public static void showToast(final Context context, final int messageResId,
            final int duration) {
        if (context == null) return;
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(context, messageResId, duration).show();
            }
        });
    }

    public static void showDialog(final Activity activity, final int dialogId) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                activity.showDialog(dialogId);
            }
        });
    }

    public static void showDialog(final Dialog dialog) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                dialog.show();
            }
        });
    }

    // Progress Dialog holder to avoid final limitation.
    private static final Vector<Dialog> sManagedProgressDialog = new Vector<Dialog>(1);

    /**
     * Show a progress dialog on current view. Call {@link #dismissProgressDialog}
     * to dismiss the dialog. If the previous progress dialog is not cancelled and a new progress
     * dialog is called, a {@link UDeliveryException} will be thrown.
     *
     * @param context
     * @param message
     */
    public static void showProgressDialog(final Context context, final String message) {
        if (!sManagedProgressDialog.isEmpty())
                throw new SmartHostsException("Progress dialog is showing. Close it first.");

        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                ProgressDialog progressDialog = new ProgressDialog(context);
                progressDialog.setMessage(message);
                progressDialog.setIndeterminate(true);
                progressDialog.setCancelable(false);
                progressDialog.show();
                sManagedProgressDialog.add(progressDialog);
            }
        });
    }

    /**
     * To dismiss the progress dialog summoned by {@link #showProgressDialog}.
     */
    public static void dismissProgressDialog() {
        if (sManagedProgressDialog.isEmpty()) {
            Log.w("Progress dialog is not showing...Ignore dismiss command.");
            return;
        }

        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                sManagedProgressDialog.get(0).dismiss();
                sManagedProgressDialog.remove(0);
            }
        });
    }

    /**
     * Show a alert dialog on current view.
     *
     * @param btnText dismiss button label
     * @param listener see {@link OnAlertDialogCloseListener}
     */
    public static void showAlertDialog(final Context context,
            final String title, final String message, final String btnText,
            final OnAlertDialogCloseListener listener) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                AlertDialog alertDialog = builder.setTitle(title)
                       .setMessage(message)
                       .setIcon(android.R.drawable.ic_dialog_alert)
                       .setCancelable(false)
                       .setNegativeButton(btnText,
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int id) {
                                    dialog.dismiss();
                                    if (listener != null) listener.onClose();
                                }
                       }).create();
                alertDialog.show();
            }
        });
    }

    /**
     * OnClose listener for dialog summoned by {@link #showAlertDialog}.
     */
    public interface OnAlertDialogCloseListener {
        public void onClose();
    }
}
